import time  # 用于计时
import pymysql  # mysql操作
import xlrd  # xls读取
from xlutils import copy  # xls数据拷贝
import pandas as pd  # xlsx操作
import random


# (host='192.168.75.130',user='local',password='123456', database='百度人员信息库')

# 灰色字体
def Fg(data, end='\n'):
    print(f'\033[0;0;37m {data}\033[0m', end=end)


# 装饰器，返回执行时间
def triple(func):
    def wrapper_triple(*args, **kwargs):
        print('\n//--------------------------')
        t = time.time()
        msg = func(*args, **kwargs)
        print('所用时间：')
        Fg(f'{time.time() - t}s')
        print('----------------------------\n')
        return msg

    return wrapper_triple


# xls文件基本类
'''datas均为二维列表！'''
class xls():
    '''
    对于xls文件的读写方法提供，好处是不用再天天写路径了，声明一个类后不算特别麻烦    # excel=xls(文件路径，分表序号)
    read（从xls中读取内容）:默认返回一个二维列表，提供初始位置和行列方式的选择     # excel.read()
                        更新对于xlsx的支持，但是没得选了，只是pandas读一下而已
    write（写入xls文件）:请将写入数据存为二维列表，提供初始位置和是否覆写的选择    # excel.write(数据[二维列表！])
    '''

    def __init__(self, 文件路径, 分表序号=0):
        self.fileway = 文件路径
        self.sheet_index = 分表序号
        # 获取文件名
        l = self.fileway[::-1].find('/')
        if l == -1:
            self.filename = self.fileway[0:]
        else:
            self.filename = self.fileway[len(self.fileway) - l:]

    def read_all(self):
        wb = xlrd.open_workbook(self.fileway)
        datas = []
        for i in range(len(wb.sheets())):
            data = []
            ws = wb.sheet_by_index(i)
            for i in range(1,ws.nrows):
                value = ws.row_values(i)
                data.append(value)
            datas.append(data)
        return datas

    def read_only(self, flag=1, func='row'):
        try:
            wb = xlrd.open_workbook(self.fileway)
            ws = wb.sheet_by_index(self.sheet_index)

            datas = []
            if (func == 'row'):
                for i in range(flag, ws.nrows):
                    value = ws.row_values(i)
                    datas.append(value)
            else:
                for i in range(flag, ws.ncols):
                    value = ws.col_values(i)
                    datas.append(value)
        except:
            df = pd.read_excel(self.fileway, sheet_name=self.sheet_index)
            datas = df.values

        return datas

    # flag用于控制起步区间，默认跳过一次，func默认为逐行读取方式，任意值为逐列
    def read(self, flag=1, func='row'):
        print('读取数据/', end='')
        try:
            wb = xlrd.open_workbook(self.fileway)
            ws = wb.sheet_by_index(self.sheet_index)

            datas = []
            if (func == 'row'):
                print(f'逐行/从第{flag}行开始')
                for i in range(flag, ws.nrows):
                    value = ws.row_values(i)
                    Fg(f'{i}:{value}')
                    datas.append(value)
            else:
                print(f'逐列/从第{flag}列开始')
                for i in range(flag, ws.ncols):
                    value = ws.col_values(i)
                    Fg(f'{i}:{value}')
                    datas.append(value)
        except:
            df = pd.read_excel(self.fileway, sheet_name=self.sheet_index)
            datas = df.values

        return datas

    # 随机读取某列内容
    def random_read(self, num, col=0):
        wb = xlrd.open_workbook(self.fileway)
        ws = wb.sheet_by_index(self.sheet_index)
        value = ws.col_values(col)
        datas = random.choices(value, k=num)

        return datas

    # col,row 用于定位初始位置，data为参数，传参方式请额外建立data=[[]],flag控制是否覆写(0为否，其余数值覆盖)
    @triple
    def write(self, datas, sheetname='Sheet', col=1, row=0, reverse=0):
        print(f'从[{row}:{col}]写入，')

        filename = self.filename

        # 打开文件，并复制内容，打开工作表
        wb = xlrd.open_workbook(self.fileway)
        new_wb = copy.copy(wb)
        write_save = new_wb.add_sheet(sheetname, cell_overwrite_ok=True)

        # 写入
        for i in range(len(datas)):
            Fg(f'{i}:', end='\t')
            for j in range(len(datas[i])):
                Fg(str(datas[i][j]), end=' |')
                if reverse == 0:
                    write_save.write(col + i, row + j, datas[i][j])
                else:
                    write_save.write(col + j, row + i, datas[i][j])
            print()
        # 保存工作簿
        new_wb.save(filename)


# mysql基础类
'''data要求为一维列表！'''
class mysql():
    '''
    __init__（初始化）:不需要调用，在新建类时需要将需要修改内容传入                            # conn = mysql()
    up（拉起连接并新建游标）:调用后连接数据库，事前准备必要内容                                 # conn.up()
    down（提交操作内容，关闭游标及连接）:调用后关闭并提交结果，最后必要内容                       # conn.down()
    sql（执行sql语句）:调用后填入sql语句，若需要拼接内容，补充相应列表即可，拼接仅支持单组数据传入   # conn.sql(sql语句，列表[不需要的时候不用写])
    check（查看结果）:调用后返回数据库结果，以return方式，效果范围与原语句一致                   # conn.check(查询参数[默认为单条,0为全部,其他数字为对应条数])
    link（查看连接内容）:打印链接信息                                                     # conn.link()
    '''

    def __init__(self, host='localhost', database='mysql', port=3306, user='root', password=''):
        self.user = user
        self.port = port
        self.host = host
        self.password = password
        self.database = database

    def link(self):
        print('\n//所属连接信息----------------')
        print('user:\t\t%s' % self.user)
        print('password:\t%s' % self.password)
        print('host:\t\t%s' % self.host)
        print('port:\t\t%s' % self.port)
        print('database:\t%s' % self.database)
        print('----------------------------\n')

    def up(self):
        self.connect = pymysql.Connect(user=self.user,  # 用户名
                                       password=self.password,  # 连接密码
                                       port=self.port,  # 所用端口号
                                       host=self.host,  # 所连IP地址
                                       database=self.database)  # 所用数据库
        self.cursor = self.connect.cursor()

    def check(self, nume=1):
        if (nume == 1):
            return self.cursor.fetchone()
        elif (nume == 0):
            return self.cursor.fetchall()
        else:
            return self.cursor.fetchmany(nume)

    def sql(self, sql, data='NULL'):
        if (data == 'NULL'):
            self.cursor.execute(sql)
        else:
            self.cursor.execute(sql, data)

    def down(self):
        self.connect.commit()
        self.cursor.close()
        self.connect.close()

    def forget(self):
        print(
            "赋权并注册:\n\tgrant all privileges on *.* to '用户名'@'IP地址' identified by '密码' with grant option;\n\tflush privileges;")
        print("增删改查(表内操作基础):\n\tINSERT INTO 表名(元素名称) VALUES(对应内容)\n\tDELETE FROM 表名 WHERE 条件\n\tUPDATE 表名 SET 结果",
              end='')
        Fg('WHERE 条件', end='')
        print(" \n\tSELECT 数据 FROM 表名", end='')
        Fg('WHERE 条件')

    def about_linux(self):
        print('网络部署')
        print('防火墙关闭')
        print('mysql安装')
        print('mysql对用户修改')
        print('mysql对权限修改')


# mysql方法封装类
class mysql_process(mysql):
    '''
    easy（流程化调用）:调用后返回结果元组，封装好的
    # conn = mysql_process()
    # conn.easy(sql语句，数据列表[不需要不用写]，查询次数[默认单次,0为全部,其余数字返回对应数据量])
    '''

    @triple
    def easy(self, sql, flag='NULL', nume=1):  # flag(数据是否拼接)
        self.up()
        self.sql(sql, flag)
        temp = self.check(nume)
        self.down()

        print('所执行的sql语句:')
        Fg(sql)
        print('结果：(%d)' % nume)
        if nume != 1:
            for i in range(len(temp)):
                Fg(f'{i}:\t{temp[i]}')
        return temp



